package proyectosudp.src;


import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Iterator;





/**
 * @author jquinterob
 * @version 1.0
 * @created 01-oct-2011 09:09:27 a.m.
 */
public class ClienteUDP {

    private String mensaje;
    private String cachePrivilegios; //variable en la que se almacenan los privilegios del usuario logueado
    DatagramSocket dgSocket;
    DatagramPacket datagram;
    final static int PORT = 8050;// puerto asignado para la comunicación con el servidor
    InetAddress destino;
    byte msg[] = new byte[8192];
    private String recibido;
    private String cedula; //variable en la que se almacena la cédula del usuario logueado
    private Dto dto;
    private Usuario usuario;



    public ClienteUDP(){
        this.mensaje = "";
    }

    /**
     *
     * @param evento
     */
    public void consultarGruposInv(){

    }

    public char consultarPrivilegios(){
            return 0;
    }

    /**
     *
     * @param evento
     */
    public void crearGrupoInv(){

    }

    /**
     * Método para crear un usuario
     * @param usuario objeto del usuario a crear
     */
    public void crearUsuario(Usuario usuario, String opcion) throws SocketException, UnknownHostException, IOException, ClassNotFoundException{
        if(getCachePrivilegios().equalsIgnoreCase("E")){
            Usuario user = usuario;
            user.setCedulaLog(getCedula());
            msg=serializar(user);
            ejecutarCliente();
            empaquetarMensaje();
            enviarMensaje();
            recibirRespuesta(msg);
            desempaquetarMensaje(datagram);
            String[] strings = dto.getRespuesta().split("#");
            if(strings[0].equalsIgnoreCase("usuarioCreado")){
                System.out.println("usuario creado/modificado");
            }
        }else{ //no tiene privilegios para crear usuarios
            Dto dto1 = new Dto();
            if(opcion.equals("crear"))
                dto1.setMensaje("generarLogRechazada#crearUsuario");
            else
                dto1.setMensaje("generarLogRechazada#modificarUsuario");
            dto1.setUsuario(getCedula());
            msg=serializar(dto1);
            ejecutarCliente();
            empaquetarMensaje();
            enviarMensaje();
            recibirRespuesta(msg);
            desempaquetarMensaje(datagram);
            String[] strings = dto.getRespuesta().split("#");
            if(strings[0].equalsIgnoreCase("creacionUsuarioRechazada")){
                //mensaje
            }
        }
    }

    /**
     *
     * @param msj
     */
    public void desempaquetarMensaje(DatagramPacket datagram) throws IOException, ClassNotFoundException{
        //en este método se debe verificar el tipo de respuesta que se retorna
        //con esta respuesta se decide que se debe mostrar en la parte gráfica
        dto = new Dto();
        dto = (Dto)desSerializar(datagram.getData());
        /*if(dto.getMensaje().equals("usuarioValidado")){ //si se el caso de uso fue validar usuario, esta es la respuesta
            setCachePrivilegios(new Character(dto.getPrivilegio()).toString());
        }else if(dto.getMensaje().equals("usuarioCreado")){
            System.out.println("--------Usuario creado-------------------");
        }else if(dto.getMensaje().equals("creacionUsuarioRechazada")){
            System.out.println("--------Usuario NO creado-------------------");
        }else if(dto.getMensaje().equals("usuarioConsultado")){
            System.out.println("--------Usuario consultado-------------------");
        }*/
    }

    /**
     *
     */
    public void ejecutarCliente() throws SocketException, UnknownHostException{
        dgSocket = new DatagramSocket();
        destino = InetAddress.getByName("localhost");
    }

    public byte[] empaquetarMensaje(){
        datagram = new DatagramPacket(msg, msg.length, destino, PORT);
        return null;
    }

    public void enviarMensaje() throws IOException{
        dgSocket.send(datagram);
    }

    /**
     *
     * @param evento
     */
    public ArrayList<Object> listarGruposInv() throws SocketException, UnknownHostException, IOException, ClassNotFoundException{
        ArrayList respuesta = new ArrayList();
        int cantidad = 1;
        for(int i = 0;i < cantidad ; i++){
            Dto dto1 = new Dto();
            dto1.setMensaje("listarGruposInv#" + i);
            dto1.setUsuario(getCedula());
            msg=serializar(dto1);
            ejecutarCliente();
            empaquetarMensaje();
            enviarMensaje();
            recibirRespuesta(msg);
            desempaquetarMensaje(datagram);
            String[] strings = dto.getRespuesta().split("#");
            if(strings[0].equalsIgnoreCase("listaGruposInvConsultados")){
                if(strings[1].equals("N")){

                }else{
                    String[] gi = dto.getRespuesta().split("#");
                    cantidad = Integer.parseInt(gi[gi.length - 1]);
                    respuesta.add(gi);
                }
            }
        }
        Iterator it = respuesta.iterator();
        dto.setListado(new ArrayList<Object>());
        while(it.hasNext()){
            String[] gi = (String[])it.next();
            GrupoInvestigacion grupo = new GrupoInvestigacion();
            grupo.setCodigoGrupoInvestigacion(gi[1]);
            grupo.setNombreGrupoInvestigacion(gi[2]);
            grupo.setUnidadAcademica(gi[3]);
            grupo.setNombreLiderGrupo(gi[4]);
            dto.getListado().add(grupo);
        }
        return dto.getListado();

    }

    /**
     *
     * @param evento
     */
    public ArrayList<Object> listarUsuarios() throws IOException, ClassNotFoundException{
        /*char a = 'N'; //por defecto el usuario no tiene privilegios
        Dto dto1 = new Dto();
        dto1.setMensaje("listarUsuarios#0");
        msg=serializar(dto1);
        ejecutarCliente();
        empaquetarMensaje();
        enviarMensaje();
        recibirRespuesta(msg);
        desempaquetarMensaje(datagram);*/
        ArrayList respuesta = new ArrayList();
        int cantidad = 1;
        for(int i = 0;i < cantidad ; i++){
            Dto dto1 = new Dto();
            dto1.setMensaje("listarUsuarios#" + i);
            dto1.setUsuario(getCedula());
            msg=serializar(dto1);
            ejecutarCliente();
            empaquetarMensaje();
            enviarMensaje();
            recibirRespuesta(msg);
            desempaquetarMensaje(datagram);
            String[] strings = dto.getRespuesta().split("#");
            if(strings[0].equalsIgnoreCase("listaUsuariosConsultados")){
                if(strings[1].equals("N")){

                }else{
                    String[] usr = dto.getRespuesta().split("#");
                    cantidad = Integer.parseInt(usr[usr.length - 1]);
                    respuesta.add(usr);
                }
            }
/*
            System.out.println("rapuests: --->" + dto.getRespuesta());
            if(dto.getRespuesta() != null){
                String[] usr = dto.getRespuesta().split("#");
                cantidad = Integer.parseInt(usr[usr.length - 1]);
                respuesta.add(usr);
            }*/
        }
        Iterator it = respuesta.iterator();
        dto.setListado(new ArrayList<Object>());
        while(it.hasNext()){
            String[] usr = (String[])it.next();
            Usuario usuario = new Usuario();
            usuario.setCedula(usr[1]);
            usuario.setNombre(usr[2]);
            usuario.setRol(usr[3]);
            usuario.setPrivilegio(usr[4]);
            usuario.setUnidadAcademica(usr[5]);
            dto.getListado().add(usuario);
        }
        return dto.getListado();
    }

    /**
     *
     * @param evento
     */
    public void modificarGrupoInv(){

    }

    /**
     *
     * @param evento
     */
    public void modificarUsuario(){

    }

    /**
     *
     * @param grupoInv
     */
    public void mostrarGrupoInv(GrupoInvestigacion grupoInv){

    }

    public void mostrarListaGruposInv(){

    }

    public void mostrarListaUsuarios(){

    }

    /**
     *
     * @param usuario
     */
    public void mostrarUsuario(Usuario usuario){

    }

    /**
     *
     * @param respuesta
     */
    public void recibirRespuesta(byte[] msg) throws IOException{
        datagram = new DatagramPacket(msg, msg.length);
        dgSocket.receive(datagram);
    }

    /**
     * Método que permite consultar los roles que posee un usuario determinado
     * y almacenar dichos roles en la variable de clase cachePrivilegios}
     * @param usuario El usuario que ingresan en el formulario
     */
    public String consultarPrivilegios(String usuario) throws SocketException, UnknownHostException, IOException, ClassNotFoundException{
        char a = 'N'; //por defecto el usuario no tiene privilegios
        mensaje = new String("usuario = "+usuario);
        Dto dto1 = new Dto();
        dto1.setMensaje("consultaPrivilegios");
        dto1.setUsuario(usuario);
        setCedula(usuario);//se almacena la cedula para posteriores almacenamientos en log
        msg=serializar(dto1);
        ejecutarCliente();
        empaquetarMensaje();
        enviarMensaje();
        recibirRespuesta(msg);
        desempaquetarMensaje(datagram); //acá se setean los privilegios e cachePrivilegios
        String[] strings = dto.getRespuesta().split("#");
        setCachePrivilegios("N");
        if(strings[0].equalsIgnoreCase("usuarioValidado")){
            setCachePrivilegios(strings[1]);
            return strings[1];
        }      
        return "N";
    }


    /**
     * Método que permite consultar un usuario
     * @param usuario El usuario que ingresan en el formulario
     */
    public String consultarUsuario(String usuario) throws SocketException, UnknownHostException, IOException, ClassNotFoundException{
        char a = 'N'; //por defecto el usuario no tiene privilegios
//        mensaje = new String("usuario = "+usuario);
        Dto dto1 = new Dto(); //se usa un dto auxiliar para mandar el mensaje
        dto1.setMensaje("consultaDatosUsuario");
        dto1.setUsuario(usuario);
        dto1.setLog(getCedula()); //se utiliza la variable log para almacenar la cédula de quien está logueado

        msg=serializar(dto1);
        ejecutarCliente();
        empaquetarMensaje();
        enviarMensaje();
        recibirRespuesta(msg);
        desempaquetarMensaje(datagram);
        String[] strings = dto.getRespuesta().split("#");
        if(strings[0].equalsIgnoreCase("usuarioConsultado")){
            return dto.getRespuesta();
        }
        return null;
    }

    public String consultarUnidades() throws SocketException, UnknownHostException, IOException, ClassNotFoundException{
        Dto dto1 = new Dto();
        dto1.setMensaje("consultaUnidadesAcademicas");
        dto1.setUsuario(getCedula());
        msg=serializar(dto1);
        ejecutarCliente();
        empaquetarMensaje();
        enviarMensaje();
        recibirRespuesta(msg);
        desempaquetarMensaje(datagram);
        String[] strings = dto.getRespuesta().split("#");
        if(strings[0].equalsIgnoreCase("unidadesConsultadas")){
            return dto.getRespuesta();
        }
        return null; //se retorna el usuario seteado en el dto global
        //return dto.getUnidadesConsultadas(); //se retorna las unidades que están seteadas en el dto global
    }

    public String getCachePrivilegios() {
        return cachePrivilegios;
    }

    public void setCachePrivilegios(String usuario) {
        this.cachePrivilegios = usuario;
    }
    public String consultarProyecto(String titulo)throws SocketException, UnknownHostException, IOException, ClassNotFoundException{
        System.out.println("consulta de un proyecto");
        mensaje = titulo;
        char a = 'N'; //por defecto el usuario no tiene privilegios
        Dto dto1 = new Dto(); //se usa un dto auxiliar para mandar el mensaje
        dto1.setMensaje("consultarUnProyecto");
        dto1.setUsuario(getCedula());
        dto1.setDatoConsulta(titulo);
        dto1.setLog(getCedula()); //se utiliza la variable log para almacenar la cédula de quien está logueado
        
        //dto.setUsuario(usuario);
        msg=serializar(dto1);
        ejecutarCliente();
        empaquetarMensaje();
        enviarMensaje();
        recibirRespuesta(msg);
        desempaquetarMensaje(datagram);
        String[] strings = dto.getRespuesta().split("#");
        if(strings[0].equalsIgnoreCase("proyectoConsultado")){
            return dto.getRespuesta();
        }
        return null;
        
        //TODO: agregar logica para convertir en objeto proyecto y usar el metodo mostrar proyecto
    }
    public void crearProyecto(Proyecto proyecto, String opcion)throws SocketException, UnknownHostException, IOException, ClassNotFoundException{
         if(getCachePrivilegios().equalsIgnoreCase("E")){
            Proyecto proy = proyecto;
            proy.setCedulaLog(getCedula());
            msg=serializar(proy);
            ejecutarCliente();
            empaquetarMensaje();
            enviarMensaje();
            recibirRespuesta(msg);
            desempaquetarMensaje(datagram);
            String[] strings = dto.getRespuesta().split("#");
            if(strings[0].equalsIgnoreCase("proyectoCreado")){
                System.out.println("proyecto creado/modificado");
            }
        }else{ //no tiene privilegios para crear usuarios
            Dto dto1 = new Dto();
            if(opcion.equals("crear"))
                dto1.setMensaje("generarLogRechazada#crearProyecto");
            else
                dto1.setMensaje("generarLogRechazada#modificarProyecto");
            
            dto1.setUsuario(getCedula());
            msg=serializar(dto1);
            ejecutarCliente();
            empaquetarMensaje();
            enviarMensaje();
            recibirRespuesta(msg);
            desempaquetarMensaje(datagram);
        }
    }

    public ArrayList<Object> listarProyectos() throws SocketException, UnknownHostException, IOException, ClassNotFoundException{
        ArrayList respuesta = new ArrayList();
        int cantidad = 1;
        for(int i = 0;i < cantidad ; i++){
            Dto dto1 = new Dto();
            dto1.setMensaje("listarProyectos#" + i);
            dto1.setUsuario(getCedula());
            msg=serializar(dto1);
            ejecutarCliente();
            empaquetarMensaje();
            enviarMensaje();
            recibirRespuesta(msg);
            desempaquetarMensaje(datagram);
            String[] strings = dto.getRespuesta().split("#");
            if(strings[0].equalsIgnoreCase("listaProyectosConsultados")){
                if(strings[1].equals("N")){

                }else{
                    String[] und = dto.getRespuesta().split("#");
                    cantidad = Integer.parseInt(und[und.length - 1]);
                    respuesta.add(und);
                }
            }
        }
        Iterator it = respuesta.iterator();
        dto.setListado(new ArrayList<Object>());
        while(it.hasNext()){
            String[] und = (String[])it.next();
            Proyecto pr = new Proyecto();
            pr.setTitulo(und[1]);
            pr.setUnidadAcademica(und[2]);
            pr.setTipo(und[3]);
            pr.setEstado(und[4]);
            dto.getListado().add(pr);
        }
        return dto.getListado();
    }

    public void modificarProyecto(){

    }
    public void mostrarListaProyectos(){

    }
    public void mostrarProyecto(Proyecto proyecto){

    }
    public String consultarUnidad(String codigo)throws SocketException, UnknownHostException, IOException, ClassNotFoundException{
//        System.out.println("consulta de una unidad");
//        mensaje = codigo;
//        char a = 'N'; //por defecto el usuario no tiene privilegios
        Dto dto1 = new Dto(); //se usa un dto auxiliar para mandar el mensaje
        dto1.setMensaje("consultarUnidad");
        dto1.setUsuario(getCedula());
        dto1.setDatoConsulta(codigo);
        dto1.setLog(getCedula()); //se utiliza la variable log para almacenar la cédula de quien está logueado

        //dto.setUsuario(usuario);
        msg=serializar(dto1);
        ejecutarCliente();
        empaquetarMensaje();
        enviarMensaje();
        recibirRespuesta(msg);
        desempaquetarMensaje(datagram);
        String[] strings = dto.getRespuesta().split("#");
        if(strings[0].equalsIgnoreCase("unidadConsultada")){
            return dto.getRespuesta();
        }
        return null; //se retorna el usuario seteado en el dto global
//        return dto.getUnidadConsultada();

        //TODO: agregar logica para convertir en objeto proyecto y usar el metodo mostrar proyecto
    }
    public void crearUnidad(UnidadAcademica unidad, String opcion)throws SocketException, UnknownHostException, IOException, ClassNotFoundException{
         if(getCachePrivilegios().equalsIgnoreCase("E")){
            UnidadAcademica uni = unidad;
            uni.setCedulaLog(getCedula());
            msg=serializar(uni);
            ejecutarCliente();
            empaquetarMensaje();
            enviarMensaje();
            recibirRespuesta(msg);
            desempaquetarMensaje(datagram);
            String[] strings = dto.getRespuesta().split("#");
            if(strings[0].equalsIgnoreCase("UnidadCreada")){
                System.out.println("unidad creada/modificada");
            }
        }else{ //no tiene privilegios para crear usuarios
            Dto dto1 = new Dto();
            if(opcion.equals("crear"))
                dto1.setMensaje("generarLogRechazada#crearUnidad");
            else
                dto1.setMensaje("generarLogRechazada#modificarUnidad");
            dto1.setUsuario(getCedula());
            msg=serializar(dto1);
            ejecutarCliente();
            empaquetarMensaje();
            enviarMensaje();
            recibirRespuesta(msg);
            desempaquetarMensaje(datagram);
            String[] strings = dto.getRespuesta().split("#");
            if(strings[0].equalsIgnoreCase("creacionUnidadRechazada")){
                //mensaje
            }
        }
    }
     public String consultarGrupoInv(String codigo)throws SocketException, UnknownHostException, IOException, ClassNotFoundException{
        System.out.println("consulta de un Grupo Investigacion");
        mensaje = codigo;
        char a = 'N'; //por defecto el usuario no tiene privilegios
        Dto dto1 = new Dto(); //se usa un dto auxiliar para mandar el mensaje
        dto1.setMensaje("consultarGrupoInv");
        dto1.setUsuario(getCedula());
        dto1.setDatoConsulta(codigo);
        dto1.setLog(getCedula()); //se utiliza la variable log para almacenar la cédula de quien está logueado

        //dto.setUsuario(usuario);
        msg=serializar(dto1);
        ejecutarCliente();
        empaquetarMensaje();
        enviarMensaje();
        recibirRespuesta(msg);
        desempaquetarMensaje(datagram);
        String[] strings = dto.getRespuesta().split("#");
        if(strings[0].equalsIgnoreCase("grupoInvConsultado")){
            return dto.getRespuesta();
        }
        return null;

        //TODO: agregar logica para convertir en objeto proyecto y usar el metodo mostrar proyecto
    }
     public void crearGrupoInv(GrupoInvestigacion grupoInv, String opcion)throws SocketException, UnknownHostException, IOException, ClassNotFoundException{
         if(getCachePrivilegios().equalsIgnoreCase("E")){
            GrupoInvestigacion grupo = grupoInv;
            grupo.setCedulaLog(getCedula());
            msg=serializar(grupo);
            ejecutarCliente();
            empaquetarMensaje();
            enviarMensaje();
            recibirRespuesta(msg);
            desempaquetarMensaje(datagram);
            String[] strings = dto.getRespuesta().split("#");
            if(strings[0].equalsIgnoreCase("GrupoCreado")){
                System.out.println("grupo inv creado/modificado");
            }
        }else{ //no tiene privilegios para crear usuarios
            Dto dto1 = new Dto();
            if(opcion.equals("crear"))
                dto1.setMensaje("generarLogRechazada#crearGrupoInv");
            else
                dto1.setMensaje("generarLogRechazada#modificarGrupoInv");
//            dto1.setMensaje("generarLogRechazada");
            dto1.setUsuario(getCedula());
            msg=serializar(dto1);
            ejecutarCliente();
            empaquetarMensaje();
            enviarMensaje();
            recibirRespuesta(msg);
            desempaquetarMensaje(datagram);
        }
    }
    //metodo para convertir a bytes un objeto
    public byte[] serializar(Object objeto){
        try{
            ByteArrayOutputStream bs= new ByteArrayOutputStream();
            ObjectOutputStream os = new ObjectOutputStream (bs);
            os.writeObject(objeto);  // this es de tipo DatoUdp
            os.flush();
            os.close();
            return  bs.toByteArray(); // devuelve byte[]
            //TODO: validar si este comportamiento es adecuado e implementar el try catch
        }catch(Exception e){
            e.printStackTrace();
        }
        return null;
    }
    //metodo para convertir en un objeto desde bytes
    public Object desSerializar(byte[] objBytes){
        try{
            System.out.println(objBytes);
            ByteArrayInputStream bs= new ByteArrayInputStream(objBytes); // bytes es el byte[]
            ObjectInputStream is = new ObjectInputStream(bs);
            Object objeto = is.readObject();
            //String[] strings = objeto.toString().split("#");
            Dto dto1 = new Dto();
            /*if(strings[0].equalsIgnoreCase("usuarioConsultado")){ //si la respuesta viene en un string (el usuario no se puede recibir en un objeto Usuario porque sale el error de espacio)
                dto1.setMensaje("usuarioConsultado");
                dto1.setUsuarioConsultado(objeto.toString());
            } else if(strings[0].equalsIgnoreCase("proyectoConsultado")){ //si la respuesta viene en un string (el usuario no se puede recibir en un objeto Usuario porque sale el error de espacio)
                dto1.setMensaje("proyectoConsultado");
                dto1.setProyectoConsultado(objeto.toString());
            }   else if(strings[0].equalsIgnoreCase("listaUsuariosConsultados")){ //si la respuesta viene en un string (el usuario no se puede recibir en un objeto Usuario porque sale el error de espacio)
                dto1.setMensaje("listaUsuariosConsultados");
                dto1.setRespuesta(objeto.toString());
            }else{
                dto1.setMensaje("unidadesConsultadas");
                dto1.setUnidadesConsultadas(objeto.toString());
            }*/
            dto1.setRespuesta(objeto.toString());
            objeto = dto1;

            /*if(objeto instanceof String){
                String[] strings = objeto.toString().split("#");
                Dto dto1 = new Dto();
                if(strings[0].equalsIgnoreCase("usuarioConsultado")){ //si la respuesta viene en un string (el usuario no se puede recibir en un objeto Usuario porque sale el error de espacio)
                    dto1.setMensaje("usuarioConsultado");
                    dto1.setUsuarioConsultado(objeto.toString());
                } else if(strings[0].equalsIgnoreCase("proyectoConsultado")){ //si la respuesta viene en un string (el usuario no se puede recibir en un objeto Usuario porque sale el error de espacio)
                    dto1.setMensaje("proyectoConsultado");
                    dto1.setProyectoConsultado(objeto.toString());
                }   else if(strings[0].equalsIgnoreCase("listaUsuariosConsultados")){ //si la respuesta viene en un string (el usuario no se puede recibir en un objeto Usuario porque sale el error de espacio)
                    dto1.setMensaje("listaUsuariosConsultados");
                    dto1.setRespuesta(objeto.toString());
                }else{
                    dto1.setMensaje("unidadesConsultadas");
                    dto1.setUnidadesConsultadas(objeto.toString());
                }
                objeto = dto1;
            }*/
            is.close();
            return objeto;
        }catch(Exception e){
            e.printStackTrace();
        }
        return null;
        //TODO: validar si este comportamiento es adecuado e implementar el try catch
    }

    public String getCedula() {
        return cedula;
    }

    public void setCedula(String cedula) {
        this.cedula = cedula;
    }

    public ArrayList<Object> listarUnidades() throws SocketException, UnknownHostException, IOException, ClassNotFoundException {
       ArrayList respuesta = new ArrayList();
        int cantidad = 1;
        for(int i = 0;i < cantidad ; i++){
            Dto dto1 = new Dto();
            dto1.setMensaje("listarUnidades#" + i);
            dto1.setUsuario(getCedula());
            msg=serializar(dto1);
            ejecutarCliente();
            empaquetarMensaje();
            enviarMensaje();
            recibirRespuesta(msg);
            desempaquetarMensaje(datagram);
            String[] strings = dto.getRespuesta().split("#");
            if(strings[0].equalsIgnoreCase("listaUnidadesConsultadas")){
                if(strings[1].equals("N")){

                }else{
                    String[] und = dto.getRespuesta().split("#");
                    cantidad = Integer.parseInt(und[und.length - 1]);
                    respuesta.add(und);
                }
            }
        }
        Iterator it = respuesta.iterator();
        dto.setListado(new ArrayList<Object>());
        while(it.hasNext()){
            String[] und = (String[])it.next();
            UnidadAcademica unidad = new UnidadAcademica();
            unidad.setCodigo(und[1]);
            unidad.setNombre(und[2]);
            dto.getListado().add(unidad);
        }
        return dto.getListado();
    }
}
